package com.i2works.smartluolong.utils.common;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import com.google.common.collect.Sets;
import com.i2works.smartluolong.utils.base.DateConstant;
import com.i2works.smartluolong.utils.base.GlobalConstant;
import com.xiaoleilu.hutool.date.DateUtil;
import com.xiaoleilu.hutool.io.FileUtil;
import com.xiaoleilu.hutool.util.CollectionUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;

/**
 * 通用工具类
 *
 * @author Liu Yutao <koal@vip.qq.com>
 * @date 2017/12/7 11:16
 */

public class BaseUtils {

    private static final Logger logger = LoggerFactory.getLogger(BaseUtils.class);


    /**
     * 获取当前网络ip
     */
    public static String getIP(HttpServletRequest request) {
        String ipAddress = request.getHeader("x-forwarded-for");
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
            if (StringUtils.equalsIgnoreCase(ipAddress, "0:0:0:0:0:0:0:1") || StringUtils.equalsIgnoreCase(ipAddress, "127.0.0.1")) {
                //根据网卡取本机配置的IP
                InetAddress inet = null;
                try {
                    inet = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
                if (inet != null) {
                    ipAddress = inet.getHostAddress();
                }
            }
        }
        //对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
        if (ipAddress != null && ipAddress.length() > 15) {
            if (ipAddress.indexOf(",") > 0) {
                ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
            }
        }
        return ipAddress;
    }


    /**
     * 获取时间字符串
     *
     * @param Param 时间格式
     */
    public static String getDate(String Param) {
        return DateFormatUtils.format(new Date(), Param);
    }

    /**
     * 获取UUID
     */
    public static String getUUID() {
        return UUID.randomUUID().toString();
    }

    /**
     * 读取txt文件的内容
     *
     * @param file 想要读取的文件对象
     * @return 返回文件内容
     */
    public static String txt2String(File file) {
        StringBuilder result = new StringBuilder();
        try {
            //构造一个BufferedReader类来读取文件
            BufferedReader br = new BufferedReader(new FileReader(file));
            String str;
            //使用readLine方法，一次读一行
            while ((str = br.readLine()) != null) {
                result.append(str.trim());
            }
            br.close();
        } catch (Exception e) {
            logger.error("文件读取失败：" + e.getMessage());
        }
        return result.toString();
    }

    /**
     * 字符串转换成List集合
     *
     * @param ids  传递字符串
     * @param regx 转换规则，默认“，”逗号
     * @author koal
     */
    public static List<String> strToList(String ids, String regx) {
        List<String> list = Lists.newArrayList();
        if (StringUtils.isNotBlank(ids)) {
            String[] strings;
            if (StringUtils.isNotBlank(regx)) {
                strings = ids.split(regx);
            } else {
                strings = ids.split(",");
            }
            Collections.addAll(list, strings);
        }
        return list;
    }

    public static Set<String> strToSet(String ids, String regx) {
        if (StringUtils.isNotBlank(ids)) {
            Set<String> list = Sets.newHashSet();
            String[] strings;
            if (StringUtils.isNotBlank(regx)) {
                strings = ids.split(regx);
            } else {
                strings = ids.split(",");
            }
            Collections.addAll(list, strings);

            return list;
        } else {
            return null;
        }
    }

    /**
     * array转换字符串
     */
    public static <T> String listToStr(List<T> List, String separator) {
        if (CollectionUtil.isEmpty(List)) {
            return null;
        }
        List<T> resultList = Lists.newArrayList();
        for (T str : List) {
            if (str != null && str != "") {
                resultList.add(str);
            }
        }
        if (StringUtils.isNotBlank(separator)) {
            return CollectionUtil.join(resultList, separator);
        }
        return CollectionUtil.join(resultList, ",");
    }


    /**
     * List转换字符串
     */
    public static <T> String listToStr(List<T> list) {
        if (CollectionUtil.isEmpty(list)) {
            return null;
        }
        StringBuilder result = new StringBuilder();
        boolean flag = false;
        for (Object obj : list) {
            if (flag) {
                result.append(",");
            } else {
                flag = true;
            }
            result.append(obj);
        }
        return result.toString();
    }

    /**
     * 泛型转换成JSON
     */
    public static <D> JSONObject getFieldToJson(D entity) {
        JSONObject result = null;
        try {
            // key是属性名，value是对应值
            result = new JSONObject();
            // 获取当前加载的实体类中所有属性（字段）
            Field[] fields = entity.getClass().getDeclaredFields();
            for (Field field : fields) {
                // 取消Java语言访问检查
                field.setAccessible(true);
                // 属性名
                String key = field.getName();
                //属性值
                Object value = field.get(entity);
                result.put(key, value);
            }
        } catch (IllegalAccessException e) {
            logger.error("BaseUtil.getFieldValue异常！" + e.getMessage());
        }
        return result;
    }

    /**
     * 获取泛型某个属性的值
     */
    public static <D, T> T getFieldValue(D entity, String fileName, Class<T> clazz) {
        // 获取当前加载的实体类中所有属性（字段）
        Field field;
        try {
            field = entity.getClass().getDeclaredField(fileName);
            // 取消Java语言访问检查(private等)
            field.setAccessible(true);
            Object result = field.get(entity);
            return clazz.cast(result);
        } catch (Exception e) {
            logger.error("BaseUtil.getFieldValue异常！" + e.getMessage());
        }
        return null;
    }

    public static String sortListToStr(List list) {
        return BaseUtils.listToStr(Ordering.natural().sortedCopy(list));
    }

    /**
     * doList 转换 voList
     */
    public static <V, D extends Serializable> List<V> do2voList(List<D> doList, Class<V> clazz) {
        try {
            V voBean;
            if (doList != null && doList.size() > 0) {
                List<V> voList = Lists.newArrayList();
                for (D doBean : doList) {
                    voBean = clazz.newInstance();
                    BeanUtils.copyProperties(doBean, voBean);
                    voList.add(voBean);
                }
                return voList;
            }
        } catch (Exception e) {
            logger.error("doList 转换 voList异常：" + e.getMessage());
        }
        return null;
    }

    /**
     * 分页格式化
     *
     * @param pageNumber 当前分页编号
     * @return 当前页从第几条开始
     * 计算：( 页码-1) * 每页几条
     * 说明：前台默认是1，后台limit默认是0，所以需要减去1才能计算正确
     */
    public static long getPageOffset(Long pageNumber) {
        long offset;
        if (pageNumber != null) {
            if (pageNumber <= 1) {
                offset = 0;
            } else {
                offset = (pageNumber - 1) * GlobalConstant.LIST_LIMIT;
            }
            return offset;
        }
        return 0;
    }


    /**
     * 获取项目路径（物理）
     */
    public static String getRootPath() {
        //取得根目录路径
        String path = BaseUtils.class.getResource("/").toString().replace("WEB-INF/classes/", "").replace("file:/", "");
        if (!path.contains(":")) {
            path = "/" + path;
        }
        return path;
    }

    /**
     * 获取项目跟路径（物理）
     */
    public static String getPath() {
        //取得根目录路径
        String path = BaseUtils.class.getResource("/").getPath();
        if (StringUtils.isNotBlank(path)) {
            return path;
        }
        return null;
    }


    /**
     * 获取静态文件下,图片的base64字符串
     *
     * @param image 图片
     */
    public static String getStaticImageBase64(String image) {
        return staticImageBase64(image, null);
    }

    /**
     * 获取静态文件下,图片的base64字符串
     *
     * @param image           图片
     * @param defaultRootPath 默认图片父路径
     */
    public static String getStaticImageBase64(String image, String defaultRootPath) {
        return staticImageBase64(image, defaultRootPath);
    }


    /**
     * 实际 获取静态文件下,图片的base64字符串 的方法
     *
     * @param image           图片
     * @param defaultRootPath 默认图片父路径
     */
    private static String staticImageBase64(String image, String defaultRootPath) {
        //存储图片完整路径的集合(有序)
        LinkedList<String> imageFullPathList = Lists.newLinkedList();
        //设置默认项目根目录下的路径
        imageFullPathList.add(BaseUtils.getRootPath() + image);
        //如果默认图片父路径不为空,再把这个地址设置进来
        if (StringUtils.isNotBlank(defaultRootPath)) {
            imageFullPathList.add(defaultRootPath + image);

        }
        //循环俩地址,如果得到后,即可返回,否则继续循环,都没有的话,返回null
        for (String imageFullPath : imageFullPathList) {
            if (FileUtil.exist(imageFullPath)) {
                String base64 = ImageConverUtil.toBase64(imageFullPath);
                if (StringUtils.isNotBlank(base64)) {
                    return base64.replaceAll("\\s*", "");
                }
            }
        }
        return null;
    }


    /**
     * 获取多少个工作日后的时间
     *
     * @param dateList      时间列表
     * @param startDate     开始时间
     * @param days          多少天后
     * @param containsToday 计算日期，是否从今日算起
     */
    public static Date workday(List<String> dateList, Date startDate, Integer days, Boolean containsToday) {
        //结束时间
        String endDate;
        //计数器
        Integer counter = containsToday ? 1 : 0;
        //下一天时间
        Date nextDate = null;
        while (true) {
            String currentDate;
            //如果下一天为空，表示为第一次循环，将当前循环时间设置为开始时间
            if (nextDate == null) {
                currentDate = DateUtils.get(startDate, DateConstant.YYYYMMDD);
            } else {
                currentDate = DateUtils.get(nextDate, DateConstant.YYYYMMDD);
            }
            if (!dateList.contains(currentDate)) {
                //如果等于指定的天数，就跳出，并记录最后日期
                if (Objects.equals(counter, days)) {
                    endDate = currentDate;
                    break;
                }
                counter++;
            }
            //每循环一次，设置下一天时间（当天时间+1）
            nextDate = DateUtil.offsetDay(DateUtils.str2Date(currentDate, DateConstant.YYYYMMDD), 1);
        }
        return DateUtils.getEndOfDay(endDate);
    }


//
//    public static void main(String[] args) {
//        List<String> dateList = Lists.newArrayList("20180101", "20180106", "20180107", "20180113", "20180114", "20180120", "20180121", "20180127", "20180128", "20180203", "20180204", "20180210", "20180215", "20180216", "20180217", "20180218", "20180219", "20180220", "20180221", "20180225", "20180303", "20180304", "20180310", "20180311", "20180317", "20180318", "20180324", "20180325", "20180331", "20180401", "20180405", "20180406", "20180407", "20180414", "20180415", "20180421", "20180422", "20180429", "20180430", "20180501", "20180505", "20180506", "20180512", "20180513", "20180519", "20180520", "20180526", "20180527", "20180602", "20180603", "20180609", "20180610", "20180616", "20180617", "20180618", "20180623", "20180624", "20180630", "20180701", "20180707", "20180708", "20180714", "20180715", "20180721", "20180722", "20180728", "20180729", "20180804", "20180805", "20180811", "20180812", "20180818", "20180819", "20180825", "20180826", "20180901", "20180902", "20180908", "20180909", "20180915", "20180916", "20180922", "20180923", "20180924", "20181001", "20181002", "20181003", "20181004", "20181005", "20181006", "20181007", "20181013", "20181014", "20181020", "20181021", "20181027", "20181028", "20181103", "20181104", "20181110", "20181111", "20181117", "20181118", "20181124", "20181125", "20181201", "20181202", "20181208", "20181209", "20181215", "20181216", "20181222", "20181223", "20181229", "20181230");
//
//        System.out.println(workday(dateList, new Date(), 10, true));
//    }

}
